This is the supplementary notes and examples for lecture 16.
It is based on data and examples seen in class
Built on the excellent tutorial from RStudio
If not already installed, the install leaflet:
install.packages("leaflet")
Then attach the library:
library(leaflet)
Bring in the other needed libraries:
library(sf)
library(tidyverse)
library(USAboundaries)
Creating a Leaflet map requires a few basic steps (not unsimular to ggplot):
Initialize a map widget by calling leaflet().
Add layers (i.e., features) to the map by using layer functions (e.g. addTiles, addMarkers, addPolygons,…)
Print the map widget to display it.
Here’s a basic example:
leaflet() %>%
addTiles() %>%
addMarkers(lng=-119.8489, lat=34.4140, popup="UCSB")
By default, leaflet sets the view of the map to the range of latitude/longitude data in the map layers
You can adjust these if needed using:
setView(): sets the center of the map view and the zoom level;
fitBounds(): fits the view into the rectangle [lng1, lat1] – [lng2, lat2];
clearBounds() clears the bound
The easiest way to add tiles is by calling addTiles() with no arguments; by default, OpenStreetMap tiles are used.
(leaflet() %>%
setView(lng=-119.8489, lat=34.4140, zoom = 12) %>%
addTiles())
Many third-party basemaps can be added using the addProviderTiles() function
As a convenience, leaflet provides a named list of all the third-party tile providers supported by the plugin: just type providers$ and choose from one of the options.
length(providers)
#> [1] 164
names(providers) %>%
head()
#> [1] "OpenStreetMap" "OpenStreetMap.Mapnik" "OpenStreetMap.DE"
#> [4] "OpenStreetMap.CH" "OpenStreetMap.France" "OpenStreetMap.HOT"
Note that some tile set providers require you to register. You can pass access tokens/keys, and other options, to the tile provider by populating the options argument with the providerTileOptions() function.
Below are a few examples:
leaflet() %>%
setView(lng=-119.8489, lat=34.4140, zoom = 12) %>%
addProviderTiles(providers$CartoDB)
leaflet() %>%
setView(lng=-119.8489, lat=34.4140, zoom = 12) %>%
addProviderTiles(providers$Stamen.Toner)
leaflet() %>%
setView(lng=-119.8489, lat=34.4140, zoom = 12) %>%
addProviderTiles(providers$Esri.WorldImagery)
leaflet() %>%
setView(lng=-119.8489, lat=34.4140, zoom = 12) %>%
addProviderTiles(providers$Stamen.TopOSMRelief)
You can stack multiple tile layers if the front tiles have some level of opacity. Here we layer the Stamen.TonerLines with aerial imagery
leaflet() %>%
setView(lng=-119.8489, lat=34.4140, zoom = 12) %>%
addProviderTiles(providers$Esri.WorldImagery) %>%
addProviderTiles(providers$Stamen.TonerLines, options = providerTileOptions(opacity = .5))
Markers are one way to identify point information on a map:
(starbucks = read_csv('data/directory.csv') %>%
filter(City %in% c("Goleta", "Santa Barbara")) %>%
st_as_sf(coords = c("Longitude", "Latitude"), crs = 4326) %>%
select(store_name = `Store Name`, phone = `Phone Number`, address = `Street Address`, city = City, brand = Brand))
#> Simple feature collection with 11 features and 5 fields
#> geometry type: POINT
#> dimension: XY
#> bbox: xmin: -119.87 ymin: 34.4 xmax: -119.65 ymax: 34.44
#> geographic CRS: WGS 84
#> # A tibble: 11 x 6
#> store_name phone address city brand geometry
#> <chr> <chr> <chr> <chr> <chr> <POINT [°]>
#> 1 Hollister & St… 805-96… 7030 Marketpla… Goleta Starb… (-119.87 34.43)
#> 2 Goleta 805-68… 173 N. Fairvie… Goleta Starb… (-119.83 34.44)
#> 3 Montecito (805) … 1046 - A Coast… Santa … Starb… (-119.65 34.42)
#> 4 State & Cota, … 805-88… 539 State Stre… Santa … Starb… (-119.7 34.42)
#> 5 Ralph's - Sant… 805-56… 100 W Carrillo… Santa … Starb… (-119.7 34.42)
#> 6 800 State Stre… (805) … 800 State Stre… Santa … Starb… (-119.7 34.42)
#> 7 W Carrillo & D… 805-89… 208 West Carri… Santa … Starb… (-119.7 34.42)
#> 8 La Cumbre Plaza 805-56… 3815 State Str… Santa … Starb… (-119.75 34.44)
#> 9 Five Points Ce… (805) … 3957 State Str… Santa … Starb… (-119.75 34.44)
#> 10 State & Victor… 805-88… 1235 State Str… Santa … Starb… (-119.71 34.42)
#> 11 1990 Cliff Dri… 805-88… 1990 Cliff Dri… Santa … Starb… (-119.72 34.4)
Markers are added using the addMarkers or addAwesomeMarkers
Their default appearance is a blue dropped pin.
As with most layer functions, - the popup argument adds a message to be displayed on click - the label argument display a text label either on hover
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addMarkers(data = starbucks, popup = ~store_name, label = ~city)
Using the Font Awesome Icons seen in lab one, we can make markers with more specific coloring and icons
We then use addAwesomeMarkers to spcifiy the icon we created using the icon argument:
icons = awesomeIcons(icon = 'coffee', markerColor = "green", library = 'fa', spin = TRUE)
leaflet(data = starbucks) %>% addProviderTiles(providers$CartoDB) %>%
addAwesomeMarkers(icon = icons, popup = ~store_name)
You can use HTML, CSS, and Java Script to modify your pop-ups
For example, we can associate the name of the Starbucks locations with their google maps URL as an hyper reference (href):
starbucks = starbucks %>%
mutate(url = paste0('https://www.google.com/maps/place/',
gsub(" ", "+", address), "+",
gsub(" ", "+", city)))
pop = paste0('<a href=', starbucks$url, '>', starbucks$store_name, "</a>")
head(pop)
#> [1] "<a href=https://www.google.com/maps/place/7030+Marketplace+Drive+Goleta>Hollister & Storke-Goleta</a>"
#> [2] "<a href=https://www.google.com/maps/place/173+N.+Fairview+Avenue+Goleta>Goleta</a>"
#> [3] "<a href=https://www.google.com/maps/place/1046+-+A+Coast+Village+Road,+Paseo+Nuevo+Shops+Santa+Barbara>Montecito</a>"
#> [4] "<a href=https://www.google.com/maps/place/539+State+Street+Santa+Barbara>State & Cota, Santa Barbara</a>"
#> [5] "<a href=https://www.google.com/maps/place/100+W+Carrillo+St+Santa+Barbara>Ralph's - Santa Barbara #680</a>"
#> [6] "<a href=https://www.google.com/maps/place/800+State+Street+Santa+Barbara>800 State Street</a>"
We can then add our custom popup to our icons:
leaflet(data = starbucks) %>%
addProviderTiles(providers$CartoDB) %>%
addAwesomeMarkers(icon = icons,
label = ~address, popup = pop)
Circle markers are much like regular circles (shapes), except their radius in onscreen pixels stays constant regardless of zoom level (z).
leaflet(data = starbucks) %>%
addProviderTiles(providers$CartoDB) %>%
addCircleMarkers(label = ~address, popup = pop)
Sometimes while mapping many points, it is useful to cluster them. For example lets plot all starbucks in the world!
all_sb = read_csv('data/directory.csv') %>%
filter(!is.na(Latitude)) %>%
st_as_sf(coords = c("Longitude", "Latitude"), crs = 4326)
leaflet(data = all_sb) %>%
addProviderTiles(providers$CartoDB) %>%
addMarkers(clusterOptions = markerClusterOptions())
The palette argument can be any of the following:
The domain is the values - named by variable - that the color palette should range over
# ?colorFactor
# Create a palette that maps factor levels to colors
pal <- colorFactor(c("darkgreen", "navy"), domain = c("Goleta", "Santa Barbara"))
leaflet(data = starbucks) %>% addProviderTiles(providers$CartoDB) %>%
addCircleMarkers(color = ~pal(city), fillOpacity = .5, stroke = FALSE)
(covid = read_csv('https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-states.csv') %>%
filter(date == max(date)) %>%
right_join(USAboundaries::us_states(), by = c("state" = "name")) %>%
filter(!stusps %in% c("AK","PR", "HI")) %>%
st_as_sf())
#> Simple feature collection with 49 features and 16 fields
#> geometry type: MULTIPOLYGON
#> dimension: XY
#> bbox: xmin: -124.7258 ymin: 24.49813 xmax: -66.9499 ymax: 49.38436
#> geographic CRS: WGS 84
#> # A tibble: 49 x 17
#> date state fips cases deaths statefp statens affgeoid geoid stusps
#> <date> <chr> <chr> <dbl> <dbl> <chr> <chr> <chr> <chr> <chr>
#> 1 2020-08-27 Alab… 01 121023 2076 01 017797… 0400000… 01 AL
#> 2 2020-08-27 Ariz… 04 200172 4932 04 017797… 0400000… 04 AZ
#> 3 2020-08-27 Arka… 05 58745 739 05 000680… 0400000… 05 AR
#> 4 2020-08-27 Cali… 06 692962 12696 06 017797… 0400000… 06 CA
#> 5 2020-08-27 Colo… 08 56706 1937 08 017797… 0400000… 08 CO
#> 6 2020-08-27 Conn… 09 52350 4465 09 017797… 0400000… 09 CT
#> 7 2020-08-27 Dela… 10 16976 604 10 017797… 0400000… 10 DE
#> 8 2020-08-27 Dist… 11 13794 605 11 017023… 0400000… 11 DC
#> 9 2020-08-27 Flor… 12 611983 10867 12 002944… 0400000… 12 FL
#> 10 2020-08-27 Geor… 13 247017 5275 13 017053… 0400000… 13 GA
#> # … with 39 more rows, and 7 more variables: lsad <chr>, aland <dbl>,
#> # awater <dbl>, state_name <chr>, state_abbr <chr>, jurisdiction_type <chr>,
#> # geometry <MULTIPOLYGON [°]>
Adding those cases counts to polygons over a YlOrRd color ramp
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addPolygons(data = covid,
fillColor = ~colorQuantile("YlOrRd", cases)(cases),
color = NA,
label = ~state_name)
leaflet() %>%
addProviderTiles(providers$CartoDB.DarkMatter) %>%
addCircles(data = st_centroid(covid),
fillColor = ~colorQuantile("YlOrRd", cases)(cases),
color = NA,
fillOpacity = .5,
radius = ~cases/3,
label = ~cases)
https://labs.waterdata.usgs.gov/api/nldi/linked-data/nwissite/USGS-11120000/navigate/UT
Trance the Upper Tributary (UT) of the USGS-11120000
# site ID
id = "11120000"
# base URL
base ="https://labs.waterdata.usgs.gov/api/nldi/linked-data/"
# Reading sf for URLs in line
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addPolylines(data = read_sf(paste0(base,'nwissite/USGS-',id,'/navigate/UT'))) %>%
addPolygons(data = read_sf(paste0(base,'nwissite/USGS-',id,'/basin')),
fillColor = "transparent", color = "black")
WMS tiles can be added directly to a map. Here we use the NEXRAD rainfall information (refelctivity) from the Iowa Mesonet Program
(You may need to scroll out to find an)
conus = filter(us_states(), !stusps %in% c("AK", "PR", "HI"))
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addPolygons(data = st_union(conus), fillColor = "transparent",
color = "black", weight = 1) %>%
addWMSTiles(
"http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi",
layers = "nexrad-n0r-900913",
options = WMSTileOptions(format = "image/png", transparent = TRUE)
)
Uses Leaflet’s built-in layers control you can choose one of several base layers, and any number of overlay layers to view.
By defining groups, you have the ability to toogle layers, and overlays on/off.
leaflet() %>%
addProviderTiles(providers$CartoDB, group = "Grayscale") %>%
addProviderTiles(providers$Esri.WorldTerrain, group = "Terrain") %>%
addPolylines(data = read_sf(paste0(base,'nwissite/USGS-',id,'/navigate/UT'))) %>%
addPolygons(data = read_sf(paste0(base,'nwissite/USGS-',id,'/basin')), fillColor = "transparent", color = "black", group = "basin") %>%
addWMSTiles("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", layers = "nexrad-n0r-900913",
options = WMSTileOptions(format = "image/png", transparent = TRUE)) %>%
addLayersControl(overlayGroups = c("basin"), baseGroups = c("Terrain", "Grayscale"))
You can wrap your mapping code in functions to allow reusability
watershed_map = function(gage_id){
leaflet() %>%
addProviderTiles(providers$CartoDB) %>%
addPolylines(data = read_sf(paste0(base,'nwissite/USGS-',gage_id,'/navigate/UT'))) %>%
addPolygons(data = read_sf(paste0(base,'nwissite/USGS-',gage_id,'/basin')),
fillColor = "transparent", color = "black", group = "basin") %>%
addWMSTiles("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", layers = "nexrad-n0r-900913",
options = WMSTileOptions(format = "image/png", transparent = TRUE))
}
watershed_map("07382000")
watershed_map("07382000") %>%
addMeasure() %>%
addGraticule() %>%
addMiniMap()
watershed_map("07382000") %>%
addMeasure() %>%
addGraticule() %>%
leafem::addHomeButton(group = "basin") %>%
leafem::addMouseCoordinates()
leaflet(data = starbucks) %>%
addProviderTiles(providers$CartoDB) %>%
addCircleMarkers(
color = ~pal(city),
fillOpacity = .5,
stroke = FALSE,
popup = leafpop::popupTable(starbucks)
)
Making that table nicer…
leaflet(data = starbucks) %>% addProviderTiles(providers$CartoDB) %>%
addCircleMarkers(
color = ~pal(city), fillOpacity = .5,
stroke = FALSE,
popup = leafpop::popupTable(st_drop_geometry(starbucks[,1:5]), feature.id = FALSE, row.numbers = FALSE)
)
leafem and leafpop functionalitieslibrary(mapview)
mapview(starbucks)